use std::collections::HashMap;
use std::{fs, io};
use std::fs::{copy, File};
use std::io::{sink, BufReader};
use std::sync::Arc;
use reqwest::Certificate;
use crate::http::http_request::HttpRequest;
use crate::http::http_router;
use tokio::io::{split, AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpListener;
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer};
use tokio_rustls::rustls::pki_types::pem::PemObject;
use tokio_rustls::rustls::ServerConfig;
use tokio_rustls::{rustls, TlsAcceptor};
use tracing::{debug, error, info, warn, Level};
use tracing::field::debug;
use tracing_subscriber::FmtSubscriber;
use crate::filter::session_filter;
use crate::http::http_response::{HttpResponse, HttpStatusCode};

pub async fn run() {

    let listener = TcpListener::bind("0.0.0.0:8080").await.unwrap();
    info!("listener in 8080");

    loop {
        let (socket, _) = listener.accept().await.unwrap();
        tokio::spawn(async move {
            handle(socket).await;
        });
    }
}

async fn handle(mut socket: tokio::net::TcpStream) {
    info!("new connection accepted");
    let mut buf = [0; 2048];
    loop {
        match socket.read(&mut buf).await {
            Ok(n) if n == 0 => {
                info!("Connection closed");
                return;
            }
            Ok(n) => {
                debug!("request buf: {}", String::from_utf8_lossy(&buf[..n]).to_string());
                // 1. 解析请求&初始化响应体
                let http_request = HttpRequest::parse_request(&buf);

                let response_headers = HashMap::new();
                let mut http_response = HttpResponse::new_empty_body(HttpStatusCode::Ok, response_headers);
                // 将读取到的字节数据转换为字符串
                info!("Received request: \n{}", http_request);
                info!("Read {} bytes", n);

                // 2. 过滤请求
                session_filter::do_filter(&http_request, &mut http_response, &socket);

                // 3. 路由请求资源
                http_router::route(&http_request, &mut http_response).await;

                // 4. 返回报文
                // let http_response = HttpResponse::ok("Hello World!".to_string());
                info!("response: \n{}", http_response);
                // 使用 to_bytes 方法将 HttpResponse 转换为字节数组
                let response_bytes = http_response.to_bytes();
                if let Err(e) = socket.write_all(&response_bytes).await {
                    eprintln!("Failed to write response: {}", e);
                }
            }
            Err(e) => {
                error!("Failed to read from socket error: {}", e);
                return;
            }
        }
    }
}




#[cfg(test)]
mod tests {
    use std::path::PathBuf;
    use std::sync::Arc;
    use maxminddb::geoip2::City;
    use maxminddb::Reader;
    use serde::de::StdError;
    use tokio::io::{copy, sink, split, AsyncWriteExt};
    use tokio::net::{TcpListener};
    use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer};
    use tokio_rustls::rustls::pki_types::pem::PemObject;
    use tokio_rustls::{rustls, TlsAcceptor};
    use tokio::{io, test};

    #[test]
    async fn test_handle() -> Result<(), Box<dyn std::error::Error>> {
        // let mut socket = tokio::net::TcpStream::connect("127.0.0.1:8080").await.unwrap();
        // let mut buf = [0; 2048];
        // let n = socket.read(&mut buf).await.unwrap();

        let reader = Reader::open_readfile("public/data/geoip2/GeoLite2-City.mmdb")?;

        // let ip = "61.141.207.179";
        let ip = "127.0.0.1";
        let result: City  = reader.lookup(ip.parse()?)?.unwrap();

        println!("IP 地址: {}", ip);

        println!("结果: {:?}", result);

        if let Some(country) = result.country {
            println!("国家代码: {}", country.iso_code.unwrap_or("Unknown")); // 输出 US
            // println!("中文名: {}", country.names.unwrap());
            // println!("英文名: {}", country.names.unwrap().get("en"));
        }

        if let Some(loc) = result.location {
            println!("坐标: ({:?}, {:?})", loc.latitude, loc.longitude);
        }

        if let Some(subdivision) = result.subdivisions {
            subdivision.iter().for_each(|subdivision| {
                println!("省份代码: {}", subdivision.iso_code.unwrap_or("Unknown")); // 输出 US
                if let Some(names) = &subdivision.names {
                    println!("中文名: {:?}", names.get("zh-CN"));
                }
                // println!("中文名: {}", subdivision.names.get("zh-CN").unwrap_or(&"未知".into()));
                // println!("英文名: {}", subdivision.names.get("en").unwrap_or(&"Unknown".into()));
            });
        }

        if let Some(continent) = result.continent {
            println!("洲代码: {}", continent.code.unwrap_or("Unknown")); // 输出 US
            // println!("中文名: {}", continent.names.get("zh-CN").unwrap_or(&"未知".into()));
            // println!("英文名: {}", continent.names.get("en").unwrap_or(&"Unknown".into()));
        }

        if let Some(postal) = result.postal {
            println!("邮编: {}", postal.code.unwrap_or("Unknown")); // 输出 US
        }


        if let Some(city) = result.city {
            println!("城市: ({:?})", city.names.unwrap().get("zh-CN"));
        }
        Ok(())
    }

    #[test]
    async fn load_config() -> Result<(), Box<dyn StdError + Send + Sync + 'static>> {

        let cert_path: PathBuf = "public/data/security/localhost.crt".parse().unwrap();
        let key_path: PathBuf = "public/data/security/localhost.key".parse().unwrap();
        println!("能进来吗0");
        let addr = "127.0.0.1:443";

        let certs = CertificateDer::pem_file_iter(cert_path)?.collect::<Result<Vec<_>, _>>()?;
        let key = PrivateKeyDer::from_pem_file(key_path)?;
        let flag_echo = false;

        let config = rustls::ServerConfig::builder()
            .with_no_client_auth()
            .with_single_cert(certs, key)?;
        let acceptor = TlsAcceptor::from(Arc::new(config));
        println!("能进来吗1");
        let listener = TcpListener::bind(&addr).await?;
        println!("能进来吗2");
        loop {
            let (stream, peer_addr) = listener.accept().await?;
            let acceptor = acceptor.clone();
            println!("能进来吗3");
            let fut = async move {
                let mut stream = acceptor.accept(stream).await?;
                println!("能进来吗4");
                if flag_echo {
                    let (mut reader, mut writer) = split(stream);
                    let n = copy(&mut reader, &mut writer).await?;
                    writer.flush().await?;
                    println!("Echo: {} - {}", peer_addr, n);
                } else {
                    println!("能进来吗5");
                    let mut output = sink();
                    println!("能进来吗6");
                    stream
                        .write_all(
                            &b"HTTP/1.0 200 ok\r\n\
                    Connection: close\r\n\
                    Content-length: 12\r\n\
                    \r\n\
                    Hello world!"[..],
                        )
                        .await?;
                    println!("能进来吗7");
                    stream.shutdown().await?;
                    copy(&mut stream, &mut output).await?;
                    println!("能进来吗8");
                    println!("Hello: {}", peer_addr);
                }

                Ok(()) as io::Result<()>
            };

            tokio::spawn(async move {
                if let Err(err) = fut.await {
                    eprintln!("{:?}", err);
                }
            });
        }

    }
}